// compile with:
// [FAILED] g++ -o sfml-ftp sfml-ftp.cc `pkg-config --cflags --libs sfml-all`


// run example like:
// 1. enter the addr of ftp server, maybe (int-dot) value, and login with ftp user password
// 2. choose a value when hints on windows
// 3. follow the guide
// 4. disconnect to ftp server

#include <SFML/Network.hpp>

#include <fstream>
#include <iostream>

std::ostream& operator<<(std::ostream& stream, const sf::Ftp::Response& resp)
{
    return stream << resp.getStatus() << resp.getMessage();
}

void showMenu()
{
    std::cout << std::endl;
    std::cout << "Choose an action:"                      << std::endl;
    std::cout << "1. Print working directory"             << std::endl;
    std::cout << "2. Print contents of working directory" << std::endl;
    std::cout << "3. Change directory"                    << std::endl;
    std::cout << "4. Create directory"                    << std::endl;
    std::cout << "5. Delete directory"                    << std::endl;
    std::cout << "6. Rename file"                         << std::endl;
    std::cout << "7. Remove file"                         << std::endl;
    std::cout << "8. Download file"                       << std::endl;
    std::cout << "9. Upload file"                         << std::endl;
    std::cout << "0. Disconnect"                          << std::endl;
    std::cout << std::endl;
}

void doIpAdress(sf::IpAddress& addr)
{
    do {
        std::cout << "Enter the FTP server address: ";
        std::cin >> addr;
    } while (addr == sf::IpAddress::None);
}

void doServerConnect(sf::Ftp svr, sf::IpAddress& addr, sf::Ftp::Response& as_resp)
{
    as_resp = svr.connect(addr);
    std::cout << as_resp << std::endl;
}

void doInputUserAndPassword(std::string& user, std::string pwd)
{
    std::cout << "User name: ";
    std::cin >> user;
    std::cout << "User password: ";
    std::cin >> pwd;
}

void doLoginResp(sf::Ftp::Response as_resp, sf::Ftp& svr, std::string& user, std::string& pwd)
{
    as_resp = svr.login(user, pwd);
    std::cout << as_resp << std::endl;
    if (!as_resp.isOk()) exit(-1);
}

void doEnterChoice(int& choice_value)
{
    std::cout << "Your choice: ";
    std::cin >> choice_value;
    std::cout << std::endl;
}

void doServerPostConnect(sf::Ftp& svr)
{
    std::cout << "Disconnecting from server..." << std::endl;
    std::cout << svr.disconnect() << std::endl;

    std::cout << "Press enter to exit..." << std::endl;
    std::cin.ignore(10000, '\n');
    std::cin.ignore(10000, '\n');
}

int main()
{
    sf::IpAddress address;
    // do {
    //     std::cout << "Enter the FTP server address: ";
    //     std::cin >> address;
    // } while (address == sf::IpAddress::None);
    doIpAdress(address);

    sf::Ftp server;
    sf::Ftp::Response connectResp;// = server.connect(address);
    // std::cout << connectResp << std::endl;
    doServerConnect(server, address, connectResp);// ERROR: deleted func

    if (!connectResp.isOk()) return -1;

    std::string username, userpassword;
    doInputUserAndPassword(username, userpassword);

    sf::Ftp::Response loginResp;// = server.login(username, userpassword);
    // std::cout << loginResp << std::endl;
    // if (!loginResp.isOk()) return -1;
    doLoginResp(loginResp, server, username, userpassword);

    int give_in_choice;

    do {
    showMenu();
    doEnterChoice(give_in_choice);

    // Main choice logic
    switch (give_in_choice)
    {
    default:
    {
        std::cout << "Invalid choice!" << std::endl;
        std::cin.clear();
        std::cin.ignore(10000, '\0');
        break;
    }

    case 0:
        break;
    
    case 1:
        {
            sf::Ftp::DirectoryResponse resp = server.getWorkingDirectory();
            std::cout << resp << std::endl;
            std::cout << "Current directory is " << resp.getDirectory() << std::endl;
            break;
        }
    
    case 2:
        {
            sf::Ftp::ListingResponse resp = server.getDirectoryListing();
            std::cout << resp << std::endl;
            const std::vector<std::string>& names = resp.getListing();
            for (std::vector<std::string>::const_iterator it = names.begin();
                it != names.end(); ++it
            ) std::cout << *it << std::endl;
            break;
        }
    
    case 3:
        {
            std::string directory;
            std::cout << "Choose a directory: ";
            std::cin >> directory;
            std::cout << server.changeDirectory(directory) << std::endl;
            break;
        }
    
    case 4:
        {
            std::string directory;
            std::cout << "Name of the directtory to create: ";
            std::cin >> directory;
            std::cout << server.createDirectory(directory) << std::endl;
            break;
        }
    
    case 5:
        {
            std::string directory;
            std::cout << "Name of the directory to remove: ";
            std::cin >> directory;
            std::cout << server.deleteDirectory(directory) << std::endl;
            break;
        }

    case 6:
        {
            std::string src, dest;
            std::cout << "Name of the file to rename: ";
            std::cin >> src;
            std::cout << "New name: ";
            std::cin >> dest;
            std::cout << server.renameFile(src, dest) << std::endl;
        }
    
    case 7:
        {
            std::string filename;
            std::cout << "Name of the file to remove: ";
            std::cin  >> filename;
            std::cout << server.deleteFile(filename) << std::endl;
            break;
        }
    
    case 8:
        {
            std::string filename, directory;
            std::cout << "Filename of the file to download (relative to current directory): ";
            std::cin  >> filename;
            std::cout << "Directory to download the file to: ";
            std::cin  >> directory;
            std::cout << server.download(filename, directory) << std::endl;
            break;
        }
    case 9:
        {
            std::string filename, directory;
            std::cout << "Path of the file to upload (absolute or relative to working directory): ";
            std::cin  >> filename;
            std::cout << "Directory to upload the file to (relative to current directory): ";
            std::cin  >> directory;
            std::cout << server.upload(filename, directory) << std::endl;
            break;
        }
        // TODO:
    } 
    
    } while (give_in_choice != 0);


    doServerPostConnect(server);
   
    return 0;
}
// END